import { withI18n, useI18n, getRequestLanguage } from "../../i18n";
import { GetServerSideProps } from "next";
import React, { FunctionComponent } from "react";
import { useLocalStore, useObserver } from "mobx-react-lite";
import "mobx-react-lite/batchingForReactDom";
import openapi from "@anyshare/openapi";
import { eacpPublicApi, getServiceNameFromApi, getErrorCodeFromService } from "../../core/config";
import {
    AppHead,
    IForgetPasswordState,
    VerificationType,
    VerificationContext,
    IForgetPasswordProps,
    SendVerification,
    ResetPassword,
} from "../../components";
import ErrorPage from "../_error";
import { getLoginRequest } from "src/services/hydra";
import classNames from "classnames";

export const ForgetPasswordForm: FunctionComponent<Omit<IForgetPasswordProps, "error">> = ({
    redirect,
    oemconfig,
    authconfig,
    isIE,
}) => {
    const { t } = useI18n();
    const store = useLocalStore<IForgetPasswordState>(() => {
        const { vcode_server_status, strong_pwd_length } = authconfig!;
        const { send_vcode_by_sms, send_vcode_by_email } = vcode_server_status;
        return {
            isVerifying: true,
            verificationId: "",
            verificationValue: "",
            verificationType: VerificationType.NONE,
            strongPasswordLength: strong_pwd_length,
            sendVcodeType: {
                sendVcodeBySMS: send_vcode_by_sms,
                sendVcodeByEmail: send_vcode_by_email,
            },
            updateVerificationValue(value: string) {
                store.verificationValue = value;
            },
            updateVerificationId(id: string) {
                store.verificationId = id;
            },
            sendVcodeSuccess(id: string, type: VerificationType, value: string) {
                store.verificationId = id;
                store.verificationType = type;
                store.verificationValue = value;
                store.isVerifying = false;
            },
            returnSendVcode() {
                store.isVerifying = true;
                store.verificationType === VerificationType.NONE;
                store.verificationValue = "";
            },
            async updatePasswordConfig() {
                const {
                    data: { vcode_server_status, strong_pwd_length },
                } = await openapi.post("/eacp/v1/auth1/getconfig", void 0);
                store.sendVcodeType = {
                    sendVcodeBySMS: (vcode_server_status as any).send_vcode_by_sms,
                    sendVcodeByEmail: (vcode_server_status as any).send_vcode_by_email,
                };
                store.strongPasswordLength = strong_pwd_length;
            },
            /**
             * 判断当前使用的验证类型
             */
            get getVerificationType() {
                if (/^[\d]{11}$/i.test(store.verificationValue)) {
                    return VerificationType.PHONE;
                } else if (
                    /^[\w\-]+(\.[\w\-]+)*@[\w\-]+(\.[\w\-]+)+$/.test(store.verificationValue) &&
                    3 < store.verificationValue.length &&
                    100 > store.verificationValue.length
                ) {
                    return VerificationType.EMAIL;
                } else {
                    return VerificationType.NONE;
                }
            },
        };
    });

    return useObserver(() => {
        return (
            <div className="top">
                <div className={classNames("oauth2-ui-wrapper", isIE ? "oauth2-ui-wrapper-ie" : null)}>
                    <AppHead oemconfig={oemconfig!} />
                    <div className="forget-password-wrapper">
                        <div className="title">{t("reset-password-title")}</div>
                        <VerificationContext.Provider value={store}>
                            {store.isVerifying ? (
                                <SendVerification
                                    t={t}
                                    redirect={redirect || `${location.protocol}//${location.hostname}:${location.port}`}
                                />
                            ) : (
                                <ResetPassword
                                    redirect={redirect || `${location.protocol}//${location.hostname}:${location.port}`}
                                    t={t}
                                />
                            )}
                        </VerificationContext.Provider>
                    </div>
                </div>
            </div>
        );
    });
};

export default withI18n<IForgetPasswordProps>(({ error, ...otherProps }) => {
    const { lang } = useI18n();

    if (error) {
        return <ErrorPage {...error} lang={lang} />;
    }
    return <ForgetPasswordForm {...otherProps} />;
});

export const getServerSideProps: GetServerSideProps<IForgetPasswordProps> = async ({ req, res, query }) => {
    const { redirect = "", login_challenge: challenge } = query;
    const requestLanguage = getRequestLanguage(req);
    const isIE = (req.headers["user-agent"] && /rv:11.0/.test(req.headers["user-agent"])) || false;
    try {
        let lastTimestamp = Date.now();
        console.log(`[${Date()}] [INFO]  {/api/eacp/v1/config/getoemconfigbysection} POST}  START`);
        // 获取通用配置
        const {
            data: { theme },
        } = await eacpPublicApi.post("/api/eacp/v1/config/getoemconfigbysection", { section: "anyshare" });

        let section: string;

        switch (requestLanguage) {
            case "zh":
            case "zh-cn":
                section = "shareweb_zh-cn";
                break;
            case "zh-tw":
            case "zh-hk":
                section = "shareweb_zh-tw";
                break;
            default:
                section = "shareweb_en-us";
                break;
        }

        // 获取oem配置
        const {
            data: { product, [`favicon.ico`]: favicon },
        } = await eacpPublicApi.post("/api/eacp/v1/config/getoemconfigbysection", { section });
        console.log(
            `[${Date()}] [INFO]  {/api/eacp/v1/config/getoemconfigbysection} POST}  SUCCESS +${
                Date.now() - lastTimestamp
            }ms`
        );
        lastTimestamp = Date.now();
        console.log(`[${Date()}] [INFO]  {/api/eacp/v1/auth1/getconfig} POST}  START`);
        // 获取认证配置
        const {
            data: { strong_pwd_length, vcode_server_status },
        } = await eacpPublicApi.post("/api/eacp/v1/auth1/getconfig", void 0);
        console.log(
            `[${Date()}] [INFO]  {/api/eacp/v1/auth1/getconfig} POST}  SUCCESS +${Date.now() - lastTimestamp}ms`
        );

        // 获取客户端类型
        let client_type = "unknown";
        if (challenge) {
            const { client } = await getLoginRequest(challenge as string);
            const metadata = (client.metadata && client.metadata.device) || {
                name: "",
                description: "",
                client_type: "unknown",
            };
            ({ client_type = "unknown" } = metadata);
        }

        return {
            props: {
                lang: requestLanguage,
                redirect: redirect as string,
                client_type: client_type,
                oemconfig: {
                    theme,
                    product,
                    favicon,
                },
                authconfig: {
                    strong_pwd_length,
                    vcode_server_status,
                },
                isIE,
            },
        };
    } catch (e) {
        const path = e && e.request && (e.request.path || (e.request._options && e.request._options.path));
        console.error(`[${Date()}] [ERROR]  ${path}  ERROR ${JSON.stringify(e && e.response && e.response.data)}`);
        if (e && e.response && e.response.status !== 503) {
            const { status, data } = e.response;
            res.statusCode = status;
            return {
                props: {
                    lang: requestLanguage,
                    redirect: redirect as string,
                    error: data,
                },
            };
        } else {
            const service = getServiceNameFromApi(path);
            console.error(`内部错误，连接${service}服务失败`);
            res.statusCode = 500;
            return {
                props: {
                    lang: requestLanguage,
                    redirect: redirect as string,
                    error: {
                        code: getErrorCodeFromService(service),
                        cause: "内部错误",
                        message: `连接${service}服务失败`,
                    },
                },
            };
        }
    }
};
